/*
Joseph Ratway
Garrett Brown
Bret Parker
*/

//imports
import java.util.*;
import java.io.*;
import java.net.*;

public class ReversiGame
{
    Board currentBoard = new Board();
    List<Board> boardStates = new ArrayList<Board>();
    Parser Parse = new Parser();
    String endgame;
	int numHumanPlayers;
	int difficulty;
	String Difficulty="";
	int startingColor=0;
	String confirm;
	String command;
	boolean displayBoard = true;
	boolean setDiff = false;
	int undoAmt=3;
	
	PrintWriter out;
	BufferedReader in; 
	
	void setupStreams(Socket socket)
	{
		try{ 
				out = new PrintWriter(socket.getOutputStream(), true);
				in  = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			} catch(IOException ex)
			{
				ex.printStackTrace();
			}
    }
	
	
    ReversiGame(Socket socket)
	{
        setupGame(socket);
    };
	
        
    void setupGame(Socket socket)
	{
        currentBoard.endCondition = 2;
        currentBoard.numMoves = 0;
		currentBoard.turnCount = 0;
		currentBoard.player = 1;
		initBoardArray();
		setInitialValues();
	}
		
          
    void initBoardArray()
	{
        for (int i=0; i < 8; i++) 
        {
            for (int j=0; j < 8; j++) 
            {
                currentBoard.currentBoard[i][j]=new BoardSpace();
                currentBoard.currentBoard[i][j].locationValue=0;
                //set weights
                if((i == 0 && j > 1 && j < 6) || (i > 1 && i < 6 && j == 0 )|| (i > 1 && i < 6 && j == 7) || (i == 7 && j > 1 && j < 6) )
                {
                    currentBoard.currentBoard[i][j].weight=4;
                }
                if((i == 1 && j > 1 && j < 6) || (i > 1 && i < 6 && j == 1 )|| (i > 1 && i < 6 && j == 6) || (i == 6 && j > 1 && j < 6))
                {
                    currentBoard.currentBoard[i][j].weight=2;
                }
                if(i > 1 && i < 6 && j > 1 && j < 6)
                {
                    currentBoard.currentBoard[i][j].weight=3;
                }
                if((i == 0 && j < 2 )|| (i  == 0 && j > 5 ) || (i == 1 && j < 2) || (i == 1 &&  j > 5) || (i == 7 && j < 2 )|| (i  == 7 && j > 5 ) || (i == 6 && j < 2) || (i == 6 &&  j > 5) )
                {
                    currentBoard.currentBoard[i][j].weight=1;
                }
                
            }
        }
	}
	
	void setInitialValues()
	{
		currentBoard.currentBoard[3][3].locationValue=2;
		currentBoard.currentBoard[3][4].locationValue=1;
		currentBoard.currentBoard[4][3].locationValue=1;
		currentBoard.currentBoard[4][4].locationValue=2;
        //set corner weights
        currentBoard.currentBoard[0][0].weight=5;
        currentBoard.currentBoard[0][7].weight=5;
        currentBoard.currentBoard[7][0].weight=5;
        currentBoard.currentBoard[7][7].weight=5;
        
	}
 
    // Function called for each new turn
    void startGame(Socket socket) //throws Exception
    {
        // Check for end of game
		if(currentBoard.endCondition==0)
		{
			if(displayBoard==true)
			{
				printBoardToClient(socket);
			}
			
			getScoresToClient("",socket);
			
			out.println("         GAME OVER");
			getScores("");
			out.println("DO YOU WANT TO PLAY AGAIN?(1=yes 2=no)");
		
			try
			{
				endgame = in.readLine();
			}
			catch(IOException ex)
			{
				ex.printStackTrace();
			}
				
			if(endgame.compareTo("1")==0)
			{	
				
				setupGame(socket);
				startGame(socket);
			}
			
			else if(endgame.compareTo("2")==0)
			{
				return;
			}
			else
			{
				System.out.println("Not a valid input");
				startGame(socket);
			}
		}
		else
		{
			Board pushBack = new Board();
			pushBack.deepCopy(currentBoard);
			boardStates.add(pushBack);
			
			setCommand(socket);
			Parse.ParseLine(this,socket);
		}
    }
	
	void setPlayers(Socket socket) // not used
	{
		String choosePlayers="";
		
		//System.out.println("How many human players? (0 = AI v AI,  1 = human v AI, 2 = human v human)" );
		//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		try{
			out = new PrintWriter(socket.getOutputStream(), true);
			out.println("How many human players? (0 = AI v AI,  1 = human v AI, 2 = human v human)");
			in  = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			choosePlayers = in.readLine();
			}
		catch(IOException ex)
			{
				ex.printStackTrace();
			}
		
		if(choosePlayers.compareTo("2")==0)
		{
			numHumanPlayers=2; //Human vs Human
			return;
		}
		else if(choosePlayers.compareTo("1")==0)	//AI vs Human
		{
			numHumanPlayers=1;
			setDifficulty(socket);
			setStartingColor(socket);
			return;
		}
		else if(choosePlayers.compareTo("0")==0)	//AI vs AI; need to think of way to set two AIs
		{
			numHumanPlayers=0;
			setDifficulty(socket);
			return;
		}
		else
		{
			System.out.println("Not a valid input");
			setPlayers(socket);
		}
	}
	
	void printBoardToClient(Socket socket) //Prints the Board
	{	
	System.out.println("trying to print to client");
	  int row = 1;
	  char valToPrint;
	 
	  try
	  {
	  
		  out = new PrintWriter(socket.getOutputStream(), true);
		  
		  out.println("Turn Count: " + currentBoard.turnCount);
		  String updateScore = "UPDATE";
		  out.println("                                         @ = Black, 0 = White");
		  out.println("    a   b   c   d   e   f   g   h  ");
		  out.println("  +---+---+---+---+---+---+---+---+");
		  for (int i=0; i < currentBoard.currentBoard.length; i++) 
		  {
		  
			out.print(row + " |");
			row++;
			
			for (int j=0; j < currentBoard.currentBoard[i].length; j++) 
			{
				if(currentBoard.currentBoard[i][j].locationValue==0)
					valToPrint=' ';
				else if(currentBoard.currentBoard[i][j].locationValue==1)
					valToPrint='@';
				else if(currentBoard.currentBoard[i][j].locationValue==2)
					valToPrint='0';
				else
					valToPrint='X';
			
				out.print(" " + valToPrint + " |");
				//System.out.print(" " + currentBoard[i][j].weight + " |");
			}
			out.println("");
			out.println("  +---+---+---+---+---+---+---+---+");
		  }
		  getScoresToClient(updateScore, socket);
		  
		  if(currentBoard.player==2)
				out.println("          WHITE'S TURN -> O ");
		  else if(currentBoard.player==1)
				out.println("          BLACK's TURN -> @ ");
		  else
				out.println("GAME OVER");
	  
	  }catch(IOException ex)
			{
				ex.printStackTrace();
			}
	  
	}
	
	void setDifficulty(Socket socket)//not used
	{
		String choiceDiff="";
		
		//System.out.println("Choose AI difficulty: (0 = Novice, 1 = Easy,  2 = Medium, 3 = Hard)");
		//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		try{	
				out = new PrintWriter(socket.getOutputStream(), true);
				out.println("Choose AI difficulty: (0 = Novice, 1 = Easy,  2 = Medium, 3 = Hard)");
				choiceDiff = in.readLine();
			}
		catch(IOException ex)
			{
				ex.printStackTrace();
			}
		
		if(choiceDiff.compareTo("2")==0)
		{
			difficulty=2;
			return;
		}
		else if(choiceDiff.compareTo("1")==0)
		{
			difficulty=1;
			return;
		}
		else if(choiceDiff.compareTo("0")==0)
		{
			difficulty=0;
			return;
		}
		else if(choiceDiff.compareTo("3")==0)
		{
			difficulty=0;
			return;
		}
		else
		{
			System.out.println("Not a valid input");
			setDifficulty(socket);
		}
	}
	
	void setStartingColor(Socket socket)//not used
	{
		String choosecolor="";
		
	//	in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		try{
				out = new PrintWriter(socket.getOutputStream(), true);
				out.println("Choose your Color: (1=White, 2=Black)");
				choosecolor = in.readLine();
			}
		catch(IOException ex)
			{
				ex.printStackTrace();
			}
		
		if(choosecolor.compareTo("2")==0)
		{
			startingColor=2;
			return;
		}
		else if(choosecolor.compareTo("1")==0)
		{
			startingColor=1;
			return;
		}
		
		else
		{
			System.out.println("Not a valid input");
			setStartingColor(socket);
		}
	}
	
	void UndoMove()
	{
	
		if(currentBoard.turnCount==0||currentBoard.turnCount==1)
			System.out.println("Can't Undo!");
			
		if(Parse.undoCount>=0)
		{
			currentBoard.turnCount-=2;
			int temp = boardStates.size()-undoAmt;
			currentBoard = boardStates.get(temp);
			//currentBoard.printBoard();
			undoAmt=undoAmt+3;
		}
	}
	
	void RedoMove()
	{
		if(Parse.undoCount>0)
		{
			undoAmt-=3;
			currentBoard.turnCount=currentBoard.turnCount+2;
			int temp = currentBoard.turnCount;
			currentBoard = boardStates.get(temp);
			currentBoard.printBoard();	
		}		
	}

	void noviceAI()//AI should choose randomly
	{
		currentBoard.random(currentBoard.currentBoard);
	}
	
	void easyAI()
	{
		currentBoard.easy(currentBoard.currentBoard);
	}
	
	void mediumAI()
	{
		currentBoard.tempPlayer=currentBoard.player;
		currentBoard.medium(currentBoard.currentBoard,0,0,"");
	}
	
	void hardAI()
	{
		currentBoard.tempPlayer=currentBoard.player;
		currentBoard.hard(currentBoard.currentBoard,0,0,"");
	}
	
	void confirmMove()
	{
		out.println("Do you want to confirm this move?(1 yes 2 no)" );
	//	in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		try{
			confirm = in.readLine();
			}
		catch(IOException ex)
			{
				ex.printStackTrace();
			}
		if(confirm=="1")
		{
			currentBoard.turnCount++;
			currentBoard.printBoard();
			
		}
		else if(confirm=="2")
		{
			
		
		}
		else
			System.out.println("Not a valid input");
	}
	
    void getScores(String str)
    {
        currentBoard.getScores(str);
    }
	
	void getScoresToClient(String str, Socket socket)
	{
		int whitePieces=0;
		int blackPieces=0;
	
		for (int i=0; i < 8; i++) 
			{
				for (int j=0; j < 8; j++) 
					{
						if(currentBoard.currentBoard[i][j].locationValue==1)
						{
							blackPieces++;
						}
						else if(currentBoard.currentBoard[i][j].locationValue==2)
						{
							whitePieces++;
						}
					}
			}
	
	
	if(str=="UPDATE")
		{
			out.println("                                           White: " + whitePieces + " Black: " + blackPieces);
		}
	else
		{
			out.println("     FINAL SCORE: White: " + whitePieces + " Black: " + blackPieces);
		}
		
	}
	
	void setCommand(Socket socket)
	{
		try{
			out = new PrintWriter(socket.getOutputStream(), true);
			out.println("Enter Your Command:");
			command = in.readLine();
			}
		catch(IOException ex)
			{
				ex.printStackTrace();
			}
	
	}
	
	
	
	
}